/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */#ifndef MOZILLA_GFX_POINT_H_#define MOZILLA_GFX_POINT_H_#include"mozilla/Attributes.h"#include"Types.h"#include"Coord.h"#include"BaseCoord.h"#include"BasePoint.h"#include"BasePoint3D.h"#include"BasePoint4D.h"#include"BaseSize.h"#include"mozilla/Maybe.h"#include"mozilla/TypeTraits.h"#include<cmath>namespacemozilla{template<typename>structIsPixel;namespacegfx{// This should only be used by the typedefs below.structUnknownUnits{};}// namespace gfxtemplate<>structIsPixel<gfx::UnknownUnits>:TrueType{};namespacegfx{/// Use this for parameters of functions to allow implicit conversions to/// integer types but not floating point types./// We use this wrapper to prevent IntSize and IntPoint's constructors to/// take foating point values as parameters, and not require their constructors/// to have implementations for each permutation of integer types.template<typenameT>structIntParam{constexprMOZ_IMPLICITIntParam(charval):value(val){}constexprMOZ_IMPLICITIntParam(unsignedcharval):value(val){}constexprMOZ_IMPLICITIntParam(shortval):value(val){}constexprMOZ_IMPLICITIntParam(unsignedshortval):value(val){}constexprMOZ_IMPLICITIntParam(intval):value(val){}constexprMOZ_IMPLICITIntParam(unsignedintval):value(val){}constexprMOZ_IMPLICITIntParam(longval):value(val){}constexprMOZ_IMPLICITIntParam(unsignedlongval):value(val){}constexprMOZ_IMPLICITIntParam(longlongval):value(val){}constexprMOZ_IMPLICITIntParam(unsignedlonglongval):value(val){}template<typenameUnit>constexprMOZ_IMPLICITIntParam(IntCoordTyped<Unit>val):value(val){}// Disable the evil ones!MOZ_IMPLICITIntParam(floatval)=delete;MOZ_IMPLICITIntParam(doubleval)=delete;Tvalue;};template<classunits,class>structPointTyped;template<classunits,class>structSizeTyped;template<classunits>structIntPointTyped:publicBasePoint<int32_t,IntPointTyped<units>,IntCoordTyped<units>>,publicunits{static_assert(IsPixel<units>::value,"'units' must be a coordinate system tag");typedefIntParam<int32_t>ToInt;typedefIntCoordTyped<units>Coord;typedefBasePoint<int32_t,IntPointTyped<units>,IntCoordTyped<units>>Super;constexprIntPointTyped():Super(){}constexprIntPointTyped(ToIntaX,ToIntaY):Super(Coord(aX.value),Coord(aY.value)){}staticIntPointTyped<units>Round(floataX,floataY){returnIntPointTyped(int32_t(floorf(aX+0.5)),int32_t(floorf(aY+0.5)));}staticIntPointTyped<units>Ceil(floataX,floataY){returnIntPointTyped(int32_t(ceil(aX)),int32_t(ceil(aY)));}staticIntPointTyped<units>Floor(floataX,floataY){returnIntPointTyped(int32_t(floorf(aX)),int32_t(floorf(aY)));}staticIntPointTyped<units>Truncate(floataX,floataY){returnIntPointTyped(int32_t(aX),int32_t(aY));}staticIntPointTyped<units>Round(constPointTyped<units,float>&aPoint);staticIntPointTyped<units>Ceil(constPointTyped<units,float>&aPoint);staticIntPointTyped<units>Floor(constPointTyped<units,float>&aPoint);staticIntPointTyped<units>Truncate(constPointTyped<units,float>&aPoint);// XXX When all of the code is ported, the following functions to convert to and from// unknown types should be removed.staticIntPointTyped<units>FromUnknownPoint(constIntPointTyped<UnknownUnits>&aPoint){returnIntPointTyped<units>(aPoint.x,aPoint.y);}IntPointTyped<UnknownUnits>ToUnknownPoint()const{returnIntPointTyped<UnknownUnits>(this->x,this->y);}};typedefIntPointTyped<UnknownUnits>IntPoint;template<classunits,classF=Float>structPointTyped:publicBasePoint<F,PointTyped<units,F>,CoordTyped<units,F>>,publicunits{static_assert(IsPixel<units>::value,"'units' must be a coordinate system tag");typedefCoordTyped<units,F>Coord;typedefBasePoint<F,PointTyped<units,F>,CoordTyped<units,F>>Super;constexprPointTyped():Super(){}constexprPointTyped(FaX,FaY):Super(Coord(aX),Coord(aY)){}// The mixed-type constructors (Float, Coord) and (Coord, Float) are needed to// avoid ambiguities because Coord is implicitly convertible to Float.constexprPointTyped(FaX,CoordaY):Super(Coord(aX),aY){}constexprPointTyped(CoordaX,FaY):Super(aX,Coord(aY)){}constexprPointTyped(CoordaX,CoordaY):Super(aX.value,aY.value){}constexprMOZ_IMPLICITPointTyped(constIntPointTyped<units>&point):Super(F(point.x),F(point.y)){}boolWithinEpsilonOf(constPointTyped<units,F>&aPoint,FaEpsilon){returnfabs(aPoint.x-this->x)<aEpsilon&&fabs(aPoint.y-this->y)<aEpsilon;}// XXX When all of the code is ported, the following functions to convert to and from// unknown types should be removed.staticPointTyped<units,F>FromUnknownPoint(constPointTyped<UnknownUnits,F>&aPoint){returnPointTyped<units,F>(aPoint.x,aPoint.y);}PointTyped<UnknownUnits,F>ToUnknownPoint()const{returnPointTyped<UnknownUnits,F>(this->x,this->y);}};typedefPointTyped<UnknownUnits>Point;typedefPointTyped<UnknownUnits,double>PointDouble;template<classunits>IntPointTyped<units>RoundedToInt(constPointTyped<units>&aPoint){returnIntPointTyped<units>::Round(aPoint.x,aPoint.y);}template<classunits>IntPointTyped<units>TruncatedToInt(constPointTyped<units>&aPoint){returnIntPointTyped<units>::Truncate(aPoint.x,aPoint.y);}template<classunits,classF=Float>structPoint3DTyped:publicBasePoint3D<F,Point3DTyped<units,F>>{static_assert(IsPixel<units>::value,"'units' must be a coordinate system tag");typedefBasePoint3D<F,Point3DTyped<units,F>>Super;Point3DTyped():Super(){}Point3DTyped(FaX,FaY,FaZ):Super(aX,aY,aZ){}// XXX When all of the code is ported, the following functions to convert to and from// unknown types should be removed.staticPoint3DTyped<units,F>FromUnknownPoint(constPoint3DTyped<UnknownUnits,F>&aPoint){returnPoint3DTyped<units,F>(aPoint.x,aPoint.y,aPoint.z);}Point3DTyped<UnknownUnits,F>ToUnknownPoint()const{returnPoint3DTyped<UnknownUnits,F>(this->x,this->y,this->z);}};typedefPoint3DTyped<UnknownUnits>Point3D;typedefPoint3DTyped<UnknownUnits,double>PointDouble3D;template<typenameunits>IntPointTyped<units>IntPointTyped<units>::Round(constPointTyped<units,float>&aPoint){returnIntPointTyped::Round(aPoint.x,aPoint.y);}template<typenameunits>IntPointTyped<units>IntPointTyped<units>::Ceil(constPointTyped<units,float>&aPoint){returnIntPointTyped::Ceil(aPoint.x,aPoint.y);}template<typenameunits>IntPointTyped<units>IntPointTyped<units>::Floor(constPointTyped<units,float>&aPoint){returnIntPointTyped::Floor(aPoint.x,aPoint.y);}template<typenameunits>IntPointTyped<units>IntPointTyped<units>::Truncate(constPointTyped<units,float>&aPoint){returnIntPointTyped::Truncate(aPoint.x,aPoint.y);}template<classunits,classF=Float>structPoint4DTyped:publicBasePoint4D<F,Point4DTyped<units,F>>{static_assert(IsPixel<units>::value,"'units' must be a coordinate system tag");typedefBasePoint4D<F,Point4DTyped<units,F>>Super;Point4DTyped():Super(){}Point4DTyped(FaX,FaY,FaZ,FaW):Super(aX,aY,aZ,aW){}explicitPoint4DTyped(constPoint3DTyped<units,F>&aPoint):Super(aPoint.x,aPoint.y,aPoint.z,1){}// XXX When all of the code is ported, the following functions to convert to and from// unknown types should be removed.staticPoint4DTyped<units,F>FromUnknownPoint(constPoint4DTyped<UnknownUnits,F>&aPoint){returnPoint4DTyped<units,F>(aPoint.x,aPoint.y,aPoint.z,aPoint.w);}Point4DTyped<UnknownUnits,F>ToUnknownPoint()const{returnPoint4DTyped<UnknownUnits,F>(this->x,this->y,this->z,this->w);}PointTyped<units,F>As2DPoint()const{returnPointTyped<units,F>(this->x/this->w,this->y/this->w);}Point3DTyped<units,F>As3DPoint()const{returnPoint3DTyped<units,F>(this->x/this->w,this->y/this->w,this->z/this->w);}};typedefPoint4DTyped<UnknownUnits>Point4D;typedefPoint4DTyped<UnknownUnits,double>PointDouble4D;template<classunits>structIntSizeTyped:publicBaseSize<int32_t,IntSizeTyped<units>>,publicunits{static_assert(IsPixel<units>::value,"'units' must be a coordinate system tag");typedefIntParam<int32_t>ToInt;typedefBaseSize<int32_t,IntSizeTyped<units>>Super;constexprIntSizeTyped():Super(){}constexprIntSizeTyped(ToIntaWidth,ToIntaHeight):Super(aWidth.value,aHeight.value){}staticIntSizeTyped<units>Round(floataWidth,floataHeight){returnIntSizeTyped(int32_t(floorf(aWidth+0.5)),int32_t(floorf(aHeight+0.5)));}staticIntSizeTyped<units>Truncate(floataWidth,floataHeight){returnIntSizeTyped(int32_t(aWidth),int32_t(aHeight));}staticIntSizeTyped<units>Ceil(floataWidth,floataHeight){returnIntSizeTyped(int32_t(ceil(aWidth)),int32_t(ceil(aHeight)));}staticIntSizeTyped<units>Floor(floataWidth,floataHeight){returnIntSizeTyped(int32_t(floorf(aWidth)),int32_t(floorf(aHeight)));}staticIntSizeTyped<units>Round(constSizeTyped<units,float>&aSize);staticIntSizeTyped<units>Ceil(constSizeTyped<units,float>&aSize);staticIntSizeTyped<units>Floor(constSizeTyped<units,float>&aSize);staticIntSizeTyped<units>Truncate(constSizeTyped<units,float>&aSize);// XXX When all of the code is ported, the following functions to convert to and from// unknown types should be removed.staticIntSizeTyped<units>FromUnknownSize(constIntSizeTyped<UnknownUnits>&aSize){returnIntSizeTyped<units>(aSize.width,aSize.height);}IntSizeTyped<UnknownUnits>ToUnknownSize()const{returnIntSizeTyped<UnknownUnits>(this->width,this->height);}};typedefIntSizeTyped<UnknownUnits>IntSize;typedefMaybe<IntSize>MaybeIntSize;template<classunits,classF=Float>structSizeTyped:publicBaseSize<F,SizeTyped<units,F>>,publicunits{static_assert(IsPixel<units>::value,"'units' must be a coordinate system tag");typedefBaseSize<F,SizeTyped<units,F>>Super;constexprSizeTyped():Super(){}constexprSizeTyped(FaWidth,FaHeight):Super(aWidth,aHeight){}explicitSizeTyped(constIntSizeTyped<units>&size):Super(F(size.width),F(size.height)){}// XXX When all of the code is ported, the following functions to convert to and from// unknown types should be removed.staticSizeTyped<units,F>FromUnknownSize(constSizeTyped<UnknownUnits,F>&aSize){returnSizeTyped<units,F>(aSize.width,aSize.height);}SizeTyped<UnknownUnits,F>ToUnknownSize()const{returnSizeTyped<UnknownUnits,F>(this->width,this->height);}};typedefSizeTyped<UnknownUnits>Size;typedefSizeTyped<UnknownUnits,double>SizeDouble;template<classunits>IntSizeTyped<units>RoundedToInt(constSizeTyped<units>&aSize){returnIntSizeTyped<units>(int32_t(floorf(aSize.width+0.5f)),int32_t(floorf(aSize.height+0.5f)));}template<typenameunits>IntSizeTyped<units>IntSizeTyped<units>::Round(constSizeTyped<units,float>&aSize){returnIntSizeTyped::Round(aSize.width,aSize.height);}template<typenameunits>IntSizeTyped<units>IntSizeTyped<units>::Ceil(constSizeTyped<units,float>&aSize){returnIntSizeTyped::Ceil(aSize.width,aSize.height);}template<typenameunits>IntSizeTyped<units>IntSizeTyped<units>::Floor(constSizeTyped<units,float>&aSize){returnIntSizeTyped::Floor(aSize.width,aSize.height);}template<typenameunits>IntSizeTyped<units>IntSizeTyped<units>::Truncate(constSizeTyped<units,float>&aSize){returnIntSizeTyped::Truncate(aSize.width,aSize.height);}}// namespace gfx}// namespace mozilla#endif /* MOZILLA_GFX_POINT_H_ */